PostgreSQL 数据库性能 操作系统优化

1 背景知识

本章主要从三个部分探讨操作系统对数据库性能的影响相关参数。

2 内核参数

2.1 SHMMAX和SHMALL配置

SHMALL: 单个共享内存段的最大值:
Linux共享内存页大小为4KB,共享内存段的大小都是共享内存页大小的整数倍。比如一个共享内存段的大小是16G时,需要共享内存页数是16GB/4KB=16777216KB/4KB=4194304(页)。

SHMMAX:共享内存页数的最大值
是核心参数中最重要的参数之一,用于定义单个共享内存段的最大值,shmmax设置应足够大,能在一个共享内存段下容纳下数据库配置的最大内存,设置的过低可能会导致需要创建多个共享内存段,可能导致系统性能的下降。

2.1.1 优化脚本

shmsetup.sh此脚本可以根据操作系统的物理限制设置合适的共享内存段。

vi ~/shmsetup.sh  

--------------------input------------------------------
#!/bin/bash
page_size=`getconf PAGE_SIZE`
phys_pages=`getconf _PHYS_PAGES`
shmall=`expr $phys_pages / 2`
shmmax=`expr $shmall \* $page_size`
echo kernel.shmmax = $shmmax
echo kernel.shmall = $shmall
chmod +x ~/shmsetup.sh 

2.1.2 设置并生效

./shmsetup.sh >> /etc/sysctl.conf
sysctl -p

2.2 fs.aio-max-nr

1、此参数限制可以同时异步请求数据的个数,设置大一些可以避免io子系统故障
2、同步io与异步io的区别可以简单理解为用户进程在功能调用后是否需要等待调用结果再去做下一次调用,同步需要等待,异步不需要等待。

2.3 fs.file-max

此参数决定了系统中所允许的文件句柄最大数目,文件句柄设置代表linux系统中可以打开的文件数量。在Linux 相关规范中最大为1024,更多请参考 C-ISO C 标准C IEEE POSIX, C XSI 限制

2.4 kernel.sem

kernel.sem = 250 162500 250 650

信号量,每16个进程一组,pg每组信号量需要17个信号量,从左到右依次是
SEMMSL 单个信号集中容纳最大信号数量,需要大于等于17,一般可以设为250
SEMMNS 整个系统中所有信号的最大数量,设置为第一个值与第四个值的乘积
SEMOPM 在单个信号集中可操作的最大信号数量,一般和第一个值相等
SEMMNI 信号集的最大值,设置为进程数/16,例如1w个连接进程,约设置为650

2.5 kernel.shmmni

kernel.shmmni = 4096 

共享内存段的最大数量
注意该参数不是shmmin,是shmmni,shmmin 表示内存段最小大小 shmmni缺省值4096 足够

2.6 net.ipv4.tcp_max_syn_backlog

net.ipv4.tcp_max_syn_backlog=4xxx 

pgpool-II 使用了这个值,用于将超过num_init_child以外的连接queue。
所以这个值决定了有多少连接可以在队列里面等待。

2.7 网络参数

net.ipv4.tcp_keepalive_intvl = 20
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_time = 60

连接空闲60秒后, 每隔20秒发心跳包, 尝试3次心跳包没有响应,关闭连接。从开始空闲,到关闭连接总共历时120秒。

2.8 vm .zone_reclaim_mode=0

**关闭 NUMA **

1、pg用0号cpu启动,那么0号cpu对应的内存就会大量使用,出现内存回收也是优先回收0号cpu对应内存。
2、当被换出页被访问时就出现响应时间变慢的问题,引起性能严重抖动。
3、当关闭了numa,内存的地位就平等了,就不会出现类似的问题。

2.9 vm .nr_hugepages

当数据库需要使用大页内存时开启,大于数据库所需共享内存即可。如何开启大页内存请参考 PostgreSQL 数据库性能 HugePages

2.10 vm.swappiness=0

是否使用Swap 空间。
vm.swappiness=0:不使用Swap 空间。
vm.swappiness=1:使用Swap 空间。

2.11 vm.overcommit_memory

0 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2 表示内核允许分配超过所有物理内存和交换空间总和的内存。

2.12 vm.overcommit_ratio=50

分配内存不能超过,物理内存*百分比+swap。
128G 16G 85%左右比较合适最多分配124GB。

2.13 vm .dirty_background_ratio

vm .dirty_background_ratio=1

这个参数指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如5%)就会触发pdflush/flush/kdmflush等后台回写进程运行,将一定缓存的脏页异步地刷入外存;

2.14 vm.dirty_ratio

vm.dirty_ratio=2
是可以用脏数据填充的绝对最大系统内存量,当系统到达此点时,必须将所有脏数据提交到磁盘,同时所有新的I/O块都会被阻塞,直到脏数据被写入磁盘。

这通常是长I/O卡顿的原因,但这也是保证内存中不会存在过量脏数据的保护机制。

3 资源限制

主要设置/etc/security/limits.conf 文件

#        - core - limits the core file size (KB)  
#        - memlock - max locked-in-memory address space (KB)  
#        - nofile - max number of open files  
#        - nproc - max number of processes
postgresql  soft nofile 1024000
postgresql hard nofile 1024000
postgresql soft nproc unlimited
postgresql hard nproc unlimited
postgresql soft core unlimited
postgresql hard core unlimited
postgresql soft memlock unlimited
postgresql hard memlock unlimited

4 SELINUX

vim /etc/sysconfig/selinux
SELINUX=disabled
SELINUXTYPE=targeted 

5 防火墙策略

根据业务场景设置,无特殊需求建议直接关闭。

6 关闭透明大页

vi /boot/grub.conf
numa=off transparent_hugepage=never

7 文件系统

7.1 磁盘挂载 noatime

默认方式下linux会把文件访问的atime做记录,比如创建时间,最近一次修改时间、访问时间等

/dev/sdd1 / xfs noatime,errors=remount-ro 0 1 

7.2 磁盘挂载 nobarrier

barrier是保证在永久存储中正确写入并排文件系统元数据的内核机制,请求前的所有队列中的请求都必须在barrier请求开始前被结束,并持久化到非易失性介质中;请求后的io需要等到其写入完成后才能得到执行

XFS mount -o nobarrier /dev/sdb1 /data/pgdata

7.3 IO scheduler

1、当为HDD机械硬盘时,使用CFQ(默认)
2、当为SSD固态硬盘时,建议使用DEADLINE。

deadline	echo deadline > /sys/block/sda/queue/scheduler 

**永久设置 **:编辑grub文件修改块设备调度策略。

vi /boot/grub.conf
elevator=deadline

7.4 4K 对齐

parted -s /dev/sda mklabel gpt
parted -s /dev/sda mkpart primary 1MiB 100%